﻿#if INTERACTIVE
#r @"D:\DEV\FSharp\Sigoogle\packages\FSPowerPack.Community.2.1.1.1\Lib\Net40\FSharp.PowerPack.Metadata.dll"
#endif

open Microsoft.FSharp.Metadata

let buildTypeSig bldr inlined ty =
  let printf format = Printf.bprintf bldr format
  let rec print depth (ty:FSharpType) =
    if ty.IsGenericParameter then 
      printf "%s%s" (if inlined then "^" else "'") ty.GenericParameter.Name
    elif ty.IsNamed then 
      if ty.GenericArguments.Count > 0 then
        if ty.NamedEntity.UsesPrefixDisplay then
          printf "%s<" ty.NamedEntity.DisplayName
          ty.GenericArguments |> Seq.iteri (fun i arg -> 
            if i > 0 then printf ", "
            print (depth + 1) arg)
          printf ">"
        else 
          let multipleArgs = ty.GenericArguments.Count >= 2
          if multipleArgs then printf "("
          ty.GenericArguments |> Seq.iteri (fun i arg -> 
            if i > 0 then printf ", "
            print (depth + 1) arg)
          if multipleArgs then printf ")"
          printf " %s" ty.NamedEntity.DisplayName
      else printf "%s" ty.NamedEntity.DisplayName
    elif ty.IsTuple then 
      ty.GenericArguments |> Seq.iteri (fun i arg -> 
        if i > 0 then printf " * "
        print (depth + 1) arg)
    elif ty.IsFunction then 
      if depth = 0 then printf "("
      ty.GenericArguments |> Seq.iteri (fun i arg -> 
        if i > 0 then 
          if ty.IsTuple then printf " * "
          else printf " -> "
        print (depth + 1) arg)
      if depth = 0 then printf ")"
  print 0 ty

let buildMemberSig bldr (mbr:FSharpMemberOrVal) = 
  let printf format = Printf.bprintf bldr format
  printf " - %s : " mbr.DisplayName 
  let inlined = 
    match mbr.InlineAnnotation with
    | FSharpInlineAnnotation.PsuedoValue -> true
    | _ -> false
  mbr.CurriedParameterGroups 
  |> Seq.iter (fun grp ->
    grp |> Seq.iteri (fun i prm ->
      if i > 0 then printf " * "
      buildTypeSig bldr inlined prm.Type)
    printf " -> ")
  buildTypeSig bldr inlined mbr.ReturnParameter.Type

let load fileName =
  let fsAsm = FSharpAssembly.FromFile(fileName)
  fsAsm.Entities 
  |> Seq.filter (fun entity -> entity.DisplayName = "Operators")
  |> Seq.iter (fun entity ->
    printfn "%s" entity.DisplayName
    entity.MembersOrValues
//    |> Seq.filter (fun mbr -> mbr.DisplayName = "( <|| )")
    |> Seq.sortBy (fun v -> v.DisplayName)
    |> Seq.iter (fun mbr ->
      let bldr = System.Text.StringBuilder()
      buildMemberSig bldr mbr
      printfn "%s" (bldr.ToString())))

load @"C:\Program Files (x86)\Reference Assemblies\Microsoft\FSharp\2.0\Runtime\v4.0\FSharp.Core.dll"

#if DEBUG
System.Console.Read() |> ignore
#endif
